package org.wxd.common.utils.http;

import com.google.common.collect.Maps;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.util.EntityUtils;

import java.io.*;
import java.nio.file.Files;
import java.nio.file.OpenOption;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Map;

/**
 * Created by wangxd on 2016/12/14.
 */
public class HttpClientUtil {

    private static PoolingHttpClientConnectionManager connMgr;
    private static RequestConfig requestConfig;
    private static final int MAX_TIMEOUT = 7000;

    static {
        // 设置连接池
        connMgr = new PoolingHttpClientConnectionManager();
        // 设置连接池大小
        connMgr.setMaxTotal(100);
        connMgr.setDefaultMaxPerRoute(connMgr.getMaxTotal());

        RequestConfig.Builder configBuilder = RequestConfig.custom();
        // 设置连接超时
        configBuilder.setConnectTimeout(MAX_TIMEOUT);
        // 设置读取超时
        configBuilder.setSocketTimeout(MAX_TIMEOUT);
        // 设置从连接池获取连接实例的超时
        configBuilder.setConnectionRequestTimeout(MAX_TIMEOUT);
        // 在提交请求之前 测试连接是否可用
        requestConfig = configBuilder.build();
    }

    private static void clear(HttpResponse response) throws HttpClientException {
        if (response == null) return;
        try {
            EntityUtils.consume(response.getEntity());
        } catch (IOException e) {
            throw new HttpClientException(e.getMessage(), e);
        }
    }

    private static HttpClient getDefaultClient() {
        return HttpClients.createDefault();
    }


    public static String doRequest(HttpRequestParam param){
        if (HttpMethod.isPost(param.method())) return doPost(param);
        return doGet(param);
    }






    private static String doPost(HttpRequestParam param) throws HttpClientException {
        HttpClient httpClient = getDefaultClient();
        HttpPost post = new HttpPost(param.url());
        post.setConfig(requestConfig);
        HttpResponse response = null;
        try {
            if (HttpContentType.isJSON(param.contentType())){
                post.addHeader("Content-type","application/json; charset=utf-8");
                post.setHeader("Accept", "application/json");
                post.setEntity(new StringEntity(param.toPostWithJson(), param.encoding()));
            }else if (HttpContentType.isTEXT(param.contentType())){
                post.addHeader("Content-type","text/plain; charset=utf-8");
                post.setHeader("Accept", "text/plain");
                post.setEntity(new UrlEncodedFormEntity(param.toPostParams(), param.encoding()));
            }
            response = httpClient.execute(post);
            HttpEntity entity = response.getEntity();
            if (entity != null){
                if (param.isStream()) {
                    entity.writeTo(param.out());
                    return null;
                }else {
                    return EntityUtils.toString(entity);
                }
            }
        } catch (IOException e) {
            throw new HttpClientException(e.getMessage(), e);
        } finally {
            clear(response);
        }
        return null;
    }


    private static String doGet(HttpRequestParam param) throws HttpClientException {
        String requestURL = param.toGetUrl();
        HttpClient httpClient = getDefaultClient();
        HttpGet get = new HttpGet(requestURL);
        HttpResponse response = null;
        try {
            response = httpClient.execute(get);
            int statusCode = response.getStatusLine().getStatusCode();
            HttpEntity entity = response.getEntity();
            System.out.println("code:" + statusCode);
            if (entity != null) return EntityUtils.toString(entity);
        } catch (IOException e) {
            throw new HttpClientException(e.getMessage(), e);
        } finally {
            clear(response);
        }
        return null;
    }


    public static void main(String[] args) throws IOException {
//        getFile("https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=d_azr0uF2tDbQKDggnObaF77TSLctb1CFcEY_YrtsFebI3Wct6VeeaSGH2m0jqGySrSsKd4093W4CAVDK69y_xsYfLcG18JEzz6GJtbWHIjCHDTUL_r7Lcd-JNq4XFDzCMQeAAALVZ","/Users/wangxd/Code/code.jpg");
        Map<String,Object> map = Maps.newHashMap();
        Path p = Paths.get("/Users/wangxd/Code/code.jpg");
        FileOutputStream fio = new FileOutputStream(p.toFile());
        map.put("scene","12332");
        map.put("width",430);
        String content = doRequest(HttpRequestParam.newBuilder()
                .method(HttpMethod.POST)
                .stream(true,fio)
                .params(map)
                .encoding("utf-8")
                .contentType(HttpContentType.JSON)
                .url("https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=d_azr0uF2tDbQKDggnObaF77TSLctb1CFcEY_YrtsFebI3Wct6VeeaSGH2m0jqGySrSsKd4093W4CAVDK69y_xsYfLcG18JEzz6GJtbWHIjCHDTUL_r7Lcd-JNq4XFDzCMQeAAALVZ").build());
        System.out.println(content);
        fio.flush();
        fio.close();
    }

    public static void getFile(String url, String destFileName)
            throws ClientProtocolException, IOException {
        // 生成一个httpclient对象
        CloseableHttpClient httpclient = HttpClients.createDefault();
        HttpPost httpget = new HttpPost(url);
        Map<String,Object> map = Maps.newHashMap();
        map.put("scene","12332");
        map.put("width",430);
        httpget.setEntity(new StringEntity(
                HttpRequestParam
                .newBuilder()
                        .url("asfsf")
                        .method(HttpMethod.POST)
                .params(map).build().toPostWithJson(),"UTF-8"));
        HttpResponse response = httpclient.execute(httpget);
        HttpEntity entity = response.getEntity();
        InputStream in = entity.getContent();
        File file = new File(destFileName);
        try {
            FileOutputStream fout = new FileOutputStream(file);
            int l = -1;
            byte[] tmp = new byte[1024];
            while ((l = in.read(tmp)) != -1) {
                fout.write(tmp, 0, l);
                // 注意这里如果用OutputStream.write(buff)的话，图片会失真，大家可以试试
            }
            fout.flush();
            fout.close();
        } finally {
            // 关闭低层流。
            in.close();
        }
        httpclient.close();
    }

}
